/*
 * Copyright (c) 2012-2012 XXXX XXXXXX, Inc.
 * XXXX Road, XXXX, XXXX State, XXXX Post code, XXXX Country.
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of XXXX
 * XXXXXX, Inc. ("Confidential Information").  You shall not
 * disclose such Confidential Information and shall use it only in
 * accordance with the terms of the license agreement you entered into
 * with XXXX.
 * 
 * History
 * Date        Ver Author        Change Description
 * ----------- --- ------------- ----------------------------------------
 * 13 Jul 2012 001 Karl          Create
 * 06 Nov 2012 002 Karl          Add function to validate image
 * 14 Nov 2012 003 Karl          Add findElement(String, WebElement)
 * 26 Dec 2012 004 Karl          Wrap WebDriverWait object
 * 06 Jan 2013 005 Karl          Add method to call window dos command
 * 05 Feb 2013 006 Karl          Add method to get current running limitation
 * 19 Mar 2013 007 Karl          IE no need to clear() before sendKeys()
 */
package com.selenium.test.util;

import java.io.File;
import java.net.URL;
import java.util.List;
import java.util.Set;

import org.openqa.selenium.Alert;
import org.openqa.selenium.By;
import org.openqa.selenium.NoAlertPresentException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.WebDriver.TargetLocator;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.Select;

import com.selenium.test.base.Page.WaitForPageToLoadStrategy;

/* 
 * wrap Selenium methods, later just make SeleniumUtil to control browser, 
 * not selenium object or driver object.
 */
public interface ISeleniumUtil {

	
	 
	/** 
	 * Make sure all selenium command sent by SeleniumUtil, unless some special 
	 * cases need driver object, such as new WebDriverWait(WebDriver driver)
	 */
	public abstract WebDriver getDriver();

	/** Navigate to a URL*/
	public abstract void get(String baseUrl);

	/** Quit browser*/
	public abstract void quit();

	/** Find element by By object*/
	public abstract WebElement findElement(By by);
	
	/** Find element by By object, if not found, throw readable message*/
	public abstract WebElement findElement(String message, By by);
	
	/** Find elements by By object*/
	public abstract List<WebElement> findElements(By by);
	
	/** Find child elements in current element */
	public abstract List<WebElement> findElements(WebElement parent, By by);
	
	/** Find link by the anchor text of this link */
	public abstract WebElement getLinkByAnchorText(String linkText);

	/** Get URL of current page*/
	public abstract String getCurrentUrl();

	/** Get current page html source*/
	public abstract String getPageSource();

	/** Get page title*/
	public abstract String getTitle();
	
	/** Get driver options */
	public abstract WebDriver.Options manage();

	/** Type keys in current input*/
	public abstract void sendKeys(WebElement element, String keys);
	
	/** Clear content first then type keys in current intput */
	public abstract void clearSendKeys(WebElement element, String keys);
	
	/** 
	 * 20 Mar 2013
	 * Special clear and send keys*/
	public abstract void specialClearSendKeys(WebElement element, String keys);
	
	/** Clear content in current input*/
	public abstract void clear(WebElement element);

	/** Click on current web element*/
	public abstract void click(WebElement element);
	
	/** Select option of a select web element, by the visible text*/
	public abstract void select(Select element, String selectStr);
	
	/**
	 * 20 Mar 2013
	 * Special select operation.
	 * */
	public abstract void specialSelect(WebElement element, String selectStr);
	
	/** If is safari browser*/
	public abstract boolean isSafari();
	
	/** If is IE browser*/
	public abstract boolean isIE();
	
	/** If is Firefox browser*/
	public abstract boolean isFirefox();
	
	/** If is IE browser*/
	public abstract boolean isChrome();
	
	/** If is Andriod webview*/
	public abstract boolean isWebview();
	
	/** 
	 * Safari not work on some element clicking - related to element not able
	 * to get focus first. this fireClick is for solve this.
	 * 
	 * Not work yet for safari. TBC.
	 * 
	 */
	public abstract void fireClick(WebElement element);
	
	/** Close browser , not used in current framework, quit() is used.*/
	public abstract void close();
	
	/** Check if a web element is displayed on current page*/
	public abstract boolean isDisplayed(WebElement element);

	/** Check if web element is enabled*/
	public abstract boolean isEnabled(WebElement element);

	/** Check if a option or checkbox is checked.*/
	public abstract boolean isSelected(WebElement element);
	
	/** Check if a web element is displayed on current page*/
	public abstract boolean isDisplayed(By by);

	/** Check if web element is enabled*/
	public abstract boolean isEnabled(By by);

	/** Check if a option or checkbox is checked.*/
	public abstract boolean isSelected(By by);
	
	/** Wait for page to load*/
	public abstract void waitForPageToLoad();
	
	/** Wait for page to load, if not done in timeOut milliseconds, raise a 
	 * error, not used in this test framework*/
	public abstract void waitForPageToLoad(int timeOutInMilliseconds);
	
	/** Given a wait for strategy, wait for page to load*/
	public abstract void waitForPageToLoad(
			WaitForPageToLoadStrategy waitStrategy);
	
	/** Wait for fixed milliseconds*/
	public void waitForFixedMilliseconds(long milliseconds);
	
	/** 
	 * select frame in relative way, just wrap selenium selectFrame(locator) 
	 * method
	 */
	public abstract void selectFrame(String locator);
	
	/** 
	 * select frame in relative way, just wrap selenium selectFrame(locator) 
	 * method
	 */
	public abstract void selectFrame(WebElement element);

	/** select default content - go back to main page*/
	public abstract void selectDefaultContent();
	
	/** switch to */
	public abstract TargetLocator switchTo();
	
	/** switch to indicated window */
	public abstract void switchToWindow(String windowHandler);
	
	public abstract Alert switchToAlert();
	
	/** bring front the window. It might do nothing at all if exception happens.*/
	public abstract void focusWindow();

	/** get current window handle*/
	public abstract String getWindowHandle();

	/** get window handles */
	public abstract Set<String> getWindowHandles();
	
	/** switch to a random new window*/
	public abstract void switchToPromptWindow(Set<String> before,
			Set<String> after);
	
	/** 
	 * <PRE>
	 * switch to prompted window after wait for some milliseconds, if no new 
	 * window prompted out after the wait period, error will be thrown out.
	 * 
	 * @throws AssertionError if no window promoted out within expected time.
	 * </PRE>
	 * */
	public abstract void switchToPromptedWindowAfterWait(Set<String> before, 
			long waitForMilliseconds) throws AssertionError;
	
	/** switch to prompted alert after wait for some milliseconds, if no new 
	 * alert prompted out after the wait period, error will be thrown out.*/
	public abstract Alert switchToPromptedAlertAfterWait(long waitForMilliseconds)
		throws NoAlertPresentException;
	
	/** create a file by URL and file name*/
	public abstract File createFileBy(URL url, String fileName);

	/**
	 * Resize currently selected window to take up the entire screen
	 */
	public abstract void windowMaximize();

	/** get screen shot and save it*/
	@SuppressWarnings("rawtypes")
	public abstract void getScreenShot(Class cls,
			String testMethodName, String shotType, String desc);

	@SuppressWarnings("rawtypes")
	public abstract void getScreenShot(Class cls,
			String testMethodName);

	@SuppressWarnings("rawtypes")
	public abstract void getScreenShot(Class cls,
			String testMethodName, String shotType);
	
	/** Check if current web driver is in unstable state, currently only one 
	 * root cause for unstable state: get() function not response in specific
	 *  time, to avoid wasting time, current test case returns directly 
	 *  while the browser is left open. */
	public abstract boolean isInUnstableState();
	
	/** DIV style select*/
	public abstract void select(ICustomDivSelect select, String visibleText);
	
	/** DIV style select control*/
	public static interface ICustomDivSelect {
		public void select(String visibleText);
	}
	
	/** wait on current page elements until they all available*/
	public abstract void waitOnElements(By[] waitOnLocators,
			int waitOnLocatorsTimeout);
	
	/** Wait on elements on current page, if any one element not exists, an 
	 * error will be posted.*/
	public abstract void waitOnElements(By[] waitOnLocators);
	
	/** wait on elements to be enabled, typical usage is for waiting on input
	 * to be enabled when page is loading. */
	public abstract void waitOnElementsEnabled(By[] waitOnLocators, int waitOnLocatorsTimeout);
	
	public abstract void waitOnElementsEnabled(By[] waitOnLocators);
	
	/** Find sub elements in current element*/
	public abstract WebElement findElement(WebElement element, By by);
	
	/** Validate if image exists*/
	public abstract void assertImgValid(String message, WebElement imgElement);
	
	/** wait for elements to load all records. */
	public abstract void waitForElementsToLoadCompletely(By list, int waitRound, int waitMillisecondsPerRound);
	
	public abstract void waitForElementsToLoadCompletely(By list, int waitRound, int waitMillisecondsPerRound, int timeoutInMillisecondsForNoRecord);
	
	/** wait for a selection to load completely*/
	public abstract void waitForSelectionToLoadCompletely(By list, int waitRound, int waitMillisecondsForEachRound);
	
	public abstract void waitForSelectionToLoadCompletely(By list, int waitRound, int waitMillisecondsForEachRound, int timeoutInMillisecondsForNoRecord);
	
	/** wait for windows to prompted completely
	 * 
	 * @param before before this calling , windows handles stores in this set
	 * @param waitRound after wait for how many rounds to make sure window prompting is completed
	 * @param waitMillisecondsPerRound wait how much time per round
	 * 
	 * If no window prompted during this waiting period, assertion error will be thrown out. 
	 * 
	 * */
	public void waitForWindowsToPromptedCompletely(Set<String> before, int waitRound,
			int waitMillisecondsPerRound);
	
	public abstract void doubleClick(WebElement element);
	
	/** 
	 * wait for a expected condition until time out.
	 * 
	 * History
	 * Date        Ver Author        Change Description
	 * ----------- --- ------------- ----------------------------------------
	 * 26 Dec 2012 004 Karl          Wrap WebDriverWait object.
	 */
	public abstract void waitForExepectedConditionUntilTimeOutInMilliseconds(
		ExpectedCondition<Boolean> booleanCondition, int timeOutInMilliseconds, 
		String message);
	
	public Object execJavaScript(String javaScript, Object ... params);
	
	public String getBrowserName();
	
    /** 
     * History
	 * 
	 * Get current running limitation info.
	 * 
	 * Date        Ver Author        Change Description
	 * ----------- --- ------------- ----------------------------------------
	 * 05 Feb 2013 006 Karl          Add method to get current running limitation
	 */
	RunningLimitation getActualRunningLimitation();
	
	public abstract void assertTextEquals(String[] expectedTexts, List<WebElement> list);
}